package org.zjvis.datascience.common.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import javafx.util.Pair;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @description JSON存取工具类
 * @date 2021-12-10
 */
public class JsonParseUtil {

    private static final String BUCKET_REGEX = "\\[(.*?)\\]|\\((.*?)\\)";


    public static Pair<String, Object> traverse(String key, Object value) {
        Integer index = null;
        Pattern p = Pattern.compile(BUCKET_REGEX);
        Matcher m = p.matcher(key);
        while (m.find()) {
            index = Integer.parseInt(m.group(1));
            key = m.replaceAll(StringUtils.EMPTY);
        }
        if (value instanceof JSONObject) {
            try {
                if (index == null) {
                    value = ((JSONObject) value).getJSONObject(key);
                } else {
                    value = ((JSONObject) value).getJSONArray(key).get(index);
                }
            } catch (ClassCastException e) {
                if (index == null) {
                    value = ((JSONObject) value).getJSONArray(key);
                } else {
                    value = ((JSONObject) value).getJSONArray(key).get(index);
                }
            } catch (JSONException e) {
                if (index == null) {
                    value = ((JSONObject) value).getOrDefault(key, new JSONObject());
                } else {
                    value = ((JSONObject) value).getOrDefault(key, new JSONArray());
                }
            }
        } else if (value instanceof JSONArray) {
            try {
                if (index == null) {
                    value = ((JSONArray) value).get(0);
                } else {
                    value = ((JSONArray) value).getJSONObject(index);
                }
            } catch (ClassCastException e) {

            }
        }
        return new Pair<>(key, value);
    }

    public static <T> T getValueByKey(String keyPath, JSONObject dataJson, Class<T> clazz) {
        String[] parts = keyPath.split("\\.");
        Object result = dataJson;
        if (parts.length > 1) {
            for (String key : parts) {
                Pair<String, Object> pair = traverse(key, result);
                result = pair.getValue();
            }
        } else {
            result = ((JSONObject) result).get(parts[0]);
        }
        if (result instanceof JSONObject) {
            return ((JSONObject) result).toJavaObject(clazz);
        } else if (result instanceof JSONArray) {
            return ((JSONArray) result).toJavaObject(clazz);
        }
        return (T) result;
    }

    public static <T> T getValueByKey(String keyPath, String dataJsonStr, Class<T> clazz) {
        String[] parts = keyPath.split("\\.");
        Object result = JSONObject.parseObject(dataJsonStr);
        if (parts.length > 1) {
            for (String key : parts) {
                Pair<String, Object> pair = traverse(key, result);
                result = pair.getValue();
            }
        } else {
            result = ((JSONObject) result).get(parts[0]);
        }
        if (result instanceof JSONObject) {
            return ((JSONObject) result).toJavaObject(clazz);
        } else if (result instanceof JSONArray) {
            return ((JSONArray) result).toJavaObject(clazz);
        }
        return (T) result;
    }

    private static void setValueByKey(Object newValue, String assignedKeyStr, JSONObject dataJson) {
        String[] parts = assignedKeyStr.split("\\.");
        Object result = dataJson;
        if (parts.length > 1) {
            for (int i = 0; i < parts.length; i++) {
                String key = parts[i];
                if (i + 1 == parts.length) {
                    ((JSONObject) result).put(key, newValue);
                } else {
                    Pair<String, Object> pair = traverse(key, result);
                    result = pair.getValue();
                }
            }
        } else {
            ((JSONObject) result).put(assignedKeyStr, newValue);
        }

    }


    public static void main(String[] args) {
        String json = "{\"isSample\":\"SUCCESS\",\"modelId\":0,\"maxParentNumber\":1,\"autoJoin\":\"yes\",\"forbidden\":false,\"message\":\"以下特征列不含有缺失值： payment_mode,\\tdeliverydistance; 以下特征列不平稳： akeed_order_id\",\"algType\":\"3\",\"parentType\":[2],\"output\":[{\"tableCols\":[\"akeed_order_id\",\"item_count\",\"payment_mode\",\"driver_accepted_time\",\"promo_code\",\"deliverydistance\",\"delivery_time\",\"preparationtime\",\"grand_total\",\"_record_id_\"],\"nodeName\":\"FILTER\",\"totalRow\":135303,\"semantic\":{\"is_favorite\":\"null\",\"created_at\":\"null\",\"promo_code\":\"null\",\"ready_for_pickup_time\":\"null\",\"delivery_time\":\"null\",\"grand_total\":\"null\",\"vendor_rating\":\"null\",\"deliverydistance\":\"null\",\"order_accepted_time\":\"null\",\"item_count\":\"null\",\"payment_mode\":\"null\",\"_record_id_\":\"null\",\"driver_rating\":\"null\",\"cid_x_loc_num_x_vendor\":\"null\",\"location_type\":\"null\",\"picked_up_time\":\"null\",\"vendor_discount_amount\":\"null\",\"delivery_date\":\"null\",\"akeed_order_id\":\"null\",\"promo_code_discount_percentage\":\"null\",\"delivered_time\":\"null\",\"is_rated\":\"null\",\"vendor_id\":\"null\",\"customer_id\":\"null\",\"driver_accepted_time\":\"null\",\"location_number\":\"null\",\"preparationtime\":\"null\"},\"columnTypes\":[\"NUMERIC\",\"NUMERIC\",\"BIGINT\",\"CHARACTER VARYING\",\"CHARACTER VARYING\",\"NUMERIC\",\"DATE\",\"CHARACTER VARYING\",\"NUMERIC\",\"INTEGER\"],\"subType\":0,\"tableName\":\"pipeline.imputation_stat_38818_1637720427591\"}],\"connected\":true,\"input\":[{\"tableCols\":[\"akeed_order_id\",\"item_count\",\"payment_mode\",\"driver_accepted_time\",\"promo_code\",\"deliverydistance\",\"delivery_time\",\"preparationtime\",\"grand_total\",\"_record_id_\"],\"nodeName\":\"FILTER\",\"totalRow\":135303,\"semantic\":{\"is_favorite\":\"null\",\"created_at\":\"null\",\"promo_code\":\"null\",\"ready_for_pickup_time\":\"null\",\"delivery_time\":\"null\",\"grand_total\":\"null\",\"vendor_rating\":\"null\",\"deliverydistance\":\"null\",\"order_accepted_time\":\"null\",\"item_count\":\"null\",\"payment_mode\":\"null\",\"_record_id_\":\"null\",\"driver_rating\":\"null\",\"cid_x_loc_num_x_vendor\":\"null\",\"location_type\":\"null\",\"picked_up_time\":\"null\",\"vendor_discount_amount\":\"null\",\"delivery_date\":\"null\",\"akeed_order_id\":\"null\",\"promo_code_discount_percentage\":\"null\",\"delivered_time\":\"null\",\"is_rated\":\"null\",\"vendor_id\":\"null\",\"customer_id\":\"null\",\"driver_accepted_time\":\"null\",\"location_number\":\"null\",\"preparationtime\":\"null\"},\"columnTypes\":[\"NUMERIC\",\"NUMERIC\",\"BIGINT\",\"CHARACTER VARYING\",\"CHARACTER VARYING\",\"NUMERIC\",\"DATE\",\"CHARACTER VARYING\",\"NUMERIC\",\"INTEGER\"],\"subType\":0,\"tableName\":\"pipeline.view_4269_38514_\"}],\"highlight\":{\"item_count\":[2.42572741194487,2.455399061032864],\"akeed_order_id\":[268618.3653846154]},\"lastTimeStamp\":1637720421461,\"parentTimeStamps\":[1637232208722],\"isSimple\":false,\"position\":{\"col\":5,\"row\":2},\"outputCols\":[],\"lastStatus\":\"SUCCESS\",\"algName\":\"缺失值插补-通用\",\"setParams\":[{\"formItem\":[{\"chineseName\":\"特征列\",\"name\":\"cols\",\"type\":\"checkboxGroup\",\"message\":\"特征列必须为数值型时间序列\",\"props\":{\"options\":[{\"label\":\"akeed_order_id\",\"value\":\"akeed_order_id\"},{\"label\":\"item_count\",\"value\":\"item_count\"},{\"label\":\"payment_mode\",\"value\":\"payment_mode\"},{\"label\":\"deliverydistance\",\"value\":\"deliverydistance\"},{\"label\":\"grand_total\",\"value\":\"grand_total\"}]}},{\"chineseName\":\"插补方法\",\"name\":\"method\",\"type\":\"select\",\"props\":{\"options\":[{\"label\":\"同期插补\",\"value\":\"period_fill\"},{\"label\":\"统计插补\",\"value\":\"stat_fill\"},{\"label\":\"线性插补\",\"value\":\"linear_fill\"}]}},{\"chineseName\":\"时间间隔\",\"name\":\"period\",\"rules\":[{\"trigger\":[\"change\",\"blur\"],\"message\":\"输入值范围为1-12(默认以月为单位）\",\"required\":true}],\"type\":\"inputNumber\",\"message\":\"输入值范围为1-12(默认以月为单位）\",\"props\":{\"min\":1,\"max\":12,\"precision\":0}},{\"chineseName\":\"统计方式\",\"name\":\"stat_method\",\"type\":\"select\",\"props\":{\"options\":[{\"label\":\"全局均数\",\"value\":\"mean_fill\"},{\"label\":\"众数\",\"value\":\"mode_fill\"},{\"label\":\"中位数\",\"value\":\"median_fill\"}]}}],\"condition\":[{\"condition\":[[{\"condition\":\"eq\",\"field\":\"method\",\"value\":\"period_fill\"}]],\"actions\":[{\"type\":\"show\",\"target\":\"period\"},{\"type\":\"hidden\",\"target\":\"stat_method\"}]},{\"condition\":[[{\"condition\":\"eq\",\"field\":\"method\",\"value\":\"stat_fill\"}]],\"actions\":[{\"type\":\"hidden\",\"target\":\"period\"},{\"type\":\"show\",\"target\":\"stat_method\"}]},{\"condition\":[[{\"condition\":\"eq\",\"field\":\"method\",\"value\":\"linear_fill\"}]],\"actions\":[{\"type\":\"hidden\",\"target\":\"period\"},{\"type\":\"hidden\",\"target\":\"stat_method\"}]}],\"intro\":\"通用插补：用非缺失数据的均值或者线性特征对缺失值进行插补。\",\"formData\":{\"period\":1,\"stat_method\":\"mean_fill\",\"method\":\"period_fill\",\"cols\":[\"akeed_order_id\",\"item_count\",\"payment_mode\",\"deliverydistance\"]}}]}";

        String json2 = "{\"config\":{\"topN\":50,\"filters\":[],\"keys\":[{\"col\":\"id_after\",\"values\":\"\",\"filterType\":\"\",\"sort\":\"asc\"}],\"values\":[{\"col\":\"count_customer_id\",\"sort\":\"\",\"topN\":50}]}}";

        JSONObject jsonObject = JSONObject.parseObject(json);
        JSONObject jsonObject2 = JSONObject.parseObject(json2);
        Object valueByKey = JsonParseUtil.getValueByKey("setParams[0].formItem[0].props.options", jsonObject, List.class);
        System.out.println(valueByKey); //[{"label":"akeed_order_id","value":"akeed_order_id"},{"label":"item_count","value":"item_count"},{"label":"payment_mode","value":"payment_mode"},{"label":"deliverydistance","value":"deliverydistance"},{"label":"grand_total","value":"grand_total"}]
//
//        Object valueByKey2 = JsonParseUtil.getValueByKey("setParams[0].formItem[0].props.options[2]", jsonObject, Map.class);
//        System.out.println(valueByKey2); //{"label":"payment_mode","value":"payment_mode"}

        Object valueByKey2 = JsonParseUtil.getValueByKey("config.keys[0].col", jsonObject2, String.class);
        System.out.println(valueByKey2);
    }

}

